package db

import (
	"common/config"
	"common/logs"
	"context"
	"github.com/redis/go-redis/v9"
	"time"
)

type RedisManager struct {
	Client        *redis.Client        // 单机
	ClusterClient *redis.ClusterClient // 集群
}

func NewRedisManager() *RedisManager {
	redisConf := config.Conf.Database.RedisConf
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	var cli *redis.Client
	var clusterCli *redis.ClusterClient
	clusterAddrs := redisConf.ClusterAddrs
	// 1. 判断是单节点还是集群
	if len(clusterAddrs) <= 0 {
		//单节点
		cli = redis.NewClient(&redis.Options{
			Addr:         redisConf.Addr,
			PoolSize:     redisConf.PoolSize,
			MinIdleConns: redisConf.MinIdleConns,
			Password:     redisConf.Password,
		})
	} else {
		//集群
		clusterCli = redis.NewClusterClient(&redis.ClusterOptions{
			Addrs:        clusterAddrs,
			PoolSize:     redisConf.PoolSize,
			MinIdleConns: redisConf.MinIdleConns,
			Password:     redisConf.Password,
		})
	}
	// 2. ping 通服务
	if clusterCli != nil {
		err := clusterCli.Ping(ctx).Err()
		if err != nil {
			logs.Fatal("redis cluster ping err: %v", err)
		}
	} else {
		err := cli.Ping(ctx).Err()
		if err != nil {
			logs.Fatal("redis ping err: %v", err)
		}
	}
	return &RedisManager{
		Client:        cli,
		ClusterClient: clusterCli,
	}
}

// Set 插入 String 元素
func (r *RedisManager) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) error {
	if r.Client != nil {
		return r.Client.Set(ctx, key, value, expiration).Err()
	} else if r.ClusterClient != nil {
		return r.ClusterClient.Set(ctx, key, value, expiration).Err()
	}
	return nil
}

func (d *RedisManager) Incr(keyName string, beginValue int64) (int64, error) {
	var exist int64 = 0
	var err error
	if d.ClusterClient != nil {
		//集群模式
		exist, err = d.ClusterClient.Exists(context.TODO(), keyName).Result()
	} else {
		exist, err = d.Client.Exists(context.TODO(), keyName).Result()
	}
	begin := false
	if exist == 0 {
		var err error = nil
		if d.ClusterClient != nil {
			err = d.ClusterClient.Set(context.TODO(), keyName, beginValue+1, 0).Err()
		} else {
			err = d.Client.Set(context.TODO(), keyName, beginValue+1, 0).Err()
		}
		if err != nil {
			return 0, err
		}
		begin = true
	}
	var id int64 = 0
	if !begin {
		if d.ClusterClient != nil {
			id, err = d.ClusterClient.Incr(context.TODO(), keyName).Result()
		} else {
			id, err = d.Client.Incr(context.TODO(), keyName).Result()
		}
	}
	if err != nil {
		return 0, err
	}
	return id, nil
}

// Close 关闭 Redis 服务
func (r *RedisManager) Close() {
	if r.ClusterClient != nil {
		if err := r.ClusterClient.Close(); err != nil {
			logs.Error("redis cluster close err: %v", err)
		}
	} else {
		if err := r.Client.Close(); err != nil {
			logs.Error("redis client close err: %v", err)
		}
	}
}
